import logging
import os
from json import loads, dumps

from PyQt5 import QtGui
from PyQt5.QtCore import Qt, QRegExp
from PyQt5.QtGui import QRegExpValidator
from PyQt5.QtWidgets import QWidget, QVBoxLayout, QCheckBox, QGridLayout, QComboBox, QLabel, QPushButton, \
    QDialog, QGroupBox, QFileDialog, QMessageBox, QPlainTextEdit, QLineEdit, QStyledItemDelegate, \
    QStyleOptionViewItem, QScrollArea

from comp_cab_setup_modules.config import config_path
from comp_cab_setup_modules.system import run_command


class TableCheckBox(QWidget):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        self.checkbox = QCheckBox()
        layout = QVBoxLayout()
        self.setLayout(layout)
        layout.addWidget(self.checkbox)
        layout.setAlignment(Qt.AlignCenter)

    def state(self) -> bool:
        """
        True, если чекбокс выбран, иначе False
        @return: выбран ли чекбокс
        """
        return self.checkbox.isChecked()

    def set_state(self, state: bool) -> None:
        """
        Устанавливает ячейку в указанное состояние
        @param state: переданное состояние
        """
        self.checkbox.setCheckState(state)

    def mousePressEvent(self, a0: QtGui.QMouseEvent) -> None:
        """
        Обработка щелчка мышью по виджету
        @param a0: событие мыши
        """
        if self.checkbox.isChecked():
            self.checkbox.setCheckState(0)
        else:
            self.checkbox.setCheckState(2)


class GetCommandForSSHRun(QDialog):

    def set_sequence_command(self) -> None:
        """
        Вводит в текстовое поле команду для последовательного выполнения на хостах
        """
        sender = self.sender()
        indx = self.buttons_text.index(sender.text())
        self.combobox.setCurrentText(self.sequence_commands[indx])

    def set_parallel_command(self) -> None:
        """
        Вводит в текстовое поле команду для последовательного выполнения на хостах
        """
        sender = self.sender()
        indx = self.buttons_text.index(sender.text())
        self.combobox.setCurrentText(self.parallel_commands[indx])

    def sequence_from_file(self) -> None:
        """
        Вводит в текстовое поле команду из выбранного файла для последовательного выполнения на хостах
        """
        file, check = QFileDialog.getOpenFileName(None, "Выберите файл со скриптом",
                                                  "", "All Files (*)")
        if check:
            self.combobox.setCurrentText(f"'bash -s' < \"{file}\"")

    def parallel_from_file(self) -> None:
        """
        Вводит в текстовое поле команду из выбранного файла для параллельного выполнения на хостах
        """
        file, check = QFileDialog.getOpenFileName(None, "Выберите файл со скриптом",
                                                  "", "All Files (*)")
        if check:
            base64_command_code = run_command(f'base64 \"{file}\"').replace('\n', '').strip()
            command = f'echo "echo {base64_command_code} | base64 -d > temp_command.txt && ' \
                      f'bash -s < temp_command.txt && rm -rf temp_command.txt" | at now'

            self.combobox.setCurrentText(f'\'{command}\'')

    def sequence_install(self) -> None:
        """
        Вводит в текстовое поле команду для последовательной установки на хостах программ из списка
        """
        window = WindowForProgramsListToInstall()
        if window.exec():
            programs = window.textarea.toPlainText().replace('\n', ' ').strip()
            self.combobox.setCurrentText('dnf -y in ' + programs)

    def parallel_install(self) -> None:
        """
        Вводит в текстовое поле команду для параллельной установки на хостах программ из списка
        """
        window = WindowForProgramsListToInstall()
        if window.exec():
            programs = window.textarea.toPlainText().replace('\n', ' ').strip()
            self.combobox.setCurrentText(f"echo 'dnf -y in {programs}' | at now")

    def sequence_remove(self) -> None:
        """
        Вводит в текстовое поле команду для последовательного удаления на хостах программ из списка
        """
        window = WindowForProgramsListToInstall(remove=True)
        if window.exec():
            programs = window.textarea.toPlainText().replace('\n', ' ').strip()
            self.combobox.setCurrentText('dnf -y remove ' + programs)

    def parallel_remove(self) -> None:
        """
        Вводит в текстовое поле команду для параллельного удаления на хостах программ из списка
        """
        window = WindowForProgramsListToInstall(remove=True)
        if window.exec():
            programs = window.textarea.toPlainText().replace('\n', ' ').strip()
            self.combobox.setCurrentText(f"echo 'dnf -y remove {programs}' | at now")

    def keyPressEvent(self, event):
        """
        Обработка нажатия Enter для вызова набранной команды
        @param event: событие клавиатуры
        """
        if event.key() == Qt.Key_Enter or event.key() == Qt.Key_Return:
            self.accept()

    def __init__(self, install_requires=False, remove_requires=False):
        super().__init__()
        self.install_requires = install_requires
        self.remove_requires = remove_requires

        self.run_cmd = False
        layout = QGridLayout()
        self.setLayout(layout)
        info_label = QLabel('Введите или выберите команду для выполнения от root на хостах:')
        layout.addWidget(info_label, 0, 0, 1, 2)
        self.combobox = QComboBox()
        self.combobox.setEditable(True)
        layout.addWidget(self.combobox, 1, 0, 1, 2)

        self.buttons_text = (
            "Обновить и перезагрузить",
            "Обновить и выключить",
            "Перезагрузить",
            "Выключить"
        )
        self.sequence_commands = (
            "dnf --refresh -y up && reboot",
            "dnf --refresh -y up && poweroff",
            "reboot",
            "poweroff"
        )
        self.parallel_commands = (
            "echo 'dnf --refresh -y up && reboot' | at now",
            "echo 'dnf --refresh -y up && poweroff' | at now",
            "echo 'reboot' | at now",
            "echo 'poweroff' | at now"
        )

        self.sequence_groupBox = QGroupBox("Последовательно")
        sequence_groupBoxLayout = QVBoxLayout(self.sequence_groupBox)
        self.parallel_groupBox = QGroupBox("Параллельно")
        parallel_groupBoxLayout = QVBoxLayout(self.parallel_groupBox)

        for i in range(len(self.buttons_text)):
            sequence_button = QPushButton(self.buttons_text[i])
            sequence_button.clicked.connect(self.set_sequence_command)
            parallel_button = QPushButton(self.buttons_text[i])
            parallel_button.clicked.connect(self.set_parallel_command)

            if i > 1:
                sequence_groupBoxLayout.addWidget(sequence_button)
                parallel_groupBoxLayout.addWidget(parallel_button)
            elif i == 1:
                self.poweroff_server_after_parallel_groupbox = QGroupBox()
                poweroff_server_after_parallel_groupbox_layout = QVBoxLayout()
                self.poweroff_server_after_parallel_groupbox.setLayout(poweroff_server_after_parallel_groupbox_layout)
                poweroff_server_after_parallel_groupbox_layout.addWidget(parallel_button)
                self.parallel_poweroff_alert_checkbox = QCheckBox('Выводить уведомление')
                poweroff_server_after_parallel_groupbox_layout.addWidget(self.parallel_poweroff_alert_checkbox)
                self.parallel_poweroff_checkbox = QCheckBox('Выключить сервер')
                poweroff_server_after_parallel_groupbox_layout.addWidget(self.parallel_poweroff_checkbox)
                parallel_groupBoxLayout.addWidget(self.poweroff_server_after_parallel_groupbox)

                self.poweroff_server_after_sequence_groupbox = QGroupBox()
                poweroff_server_after_sequence_groupbox_layout = QVBoxLayout()
                self.poweroff_server_after_sequence_groupbox.setLayout(poweroff_server_after_sequence_groupbox_layout)
                poweroff_server_after_sequence_groupbox_layout.addWidget(sequence_button)
                self.sequence_poweroff_alert_checkbox = QCheckBox('Выводить уведомление')
                poweroff_server_after_sequence_groupbox_layout.addWidget(self.sequence_poweroff_alert_checkbox)
                self.sequence_poweroff_checkbox = QCheckBox('Выключить сервер')
                poweroff_server_after_sequence_groupbox_layout.addWidget(self.sequence_poweroff_checkbox)
                sequence_groupBoxLayout.addWidget(self.poweroff_server_after_sequence_groupbox)
            elif i == 0:
                self.restart_server_after_parallel_groupbox = QGroupBox()
                restart_server_after_parallel_groupbox_layout = QVBoxLayout()
                self.restart_server_after_parallel_groupbox.setLayout(restart_server_after_parallel_groupbox_layout)
                restart_server_after_parallel_groupbox_layout.addWidget(parallel_button)
                self.parallel_restart_alert_checkbox = QCheckBox('Выводить уведомление')
                restart_server_after_parallel_groupbox_layout.addWidget(self.parallel_restart_alert_checkbox)
                parallel_groupBoxLayout.addWidget(self.restart_server_after_parallel_groupbox)

                self.restart_server_after_sequence_groupbox = QGroupBox()
                restart_server_after_sequence_groupbox_layout = QVBoxLayout()
                self.restart_server_after_sequence_groupbox.setLayout(restart_server_after_sequence_groupbox_layout)
                restart_server_after_sequence_groupbox_layout.addWidget(sequence_button)
                self.sequence_restart_alert_checkbox = QCheckBox('Выводить уведомление')
                restart_server_after_sequence_groupbox_layout.addWidget(self.sequence_restart_alert_checkbox)
                sequence_groupBoxLayout.addWidget(self.restart_server_after_sequence_groupbox)

        button = QPushButton("Установить программы...")
        button.clicked.connect(self.sequence_install)
        sequence_groupBoxLayout.addWidget(button)

        button = QPushButton("Установить программы...")
        button.clicked.connect(self.parallel_install)
        parallel_groupBoxLayout.addWidget(button)

        button = QPushButton("Удалить программы...")
        button.clicked.connect(self.sequence_remove)
        sequence_groupBoxLayout.addWidget(button)

        button = QPushButton("Удалить программы...")
        button.clicked.connect(self.parallel_remove)
        parallel_groupBoxLayout.addWidget(button)

        button = QPushButton("Из файла...")
        button.clicked.connect(self.sequence_from_file)
        sequence_groupBoxLayout.addWidget(button)

        button = QPushButton("Из файла...")
        button.clicked.connect(self.parallel_from_file)
        parallel_groupBoxLayout.addWidget(button)

        layout.addWidget(self.sequence_groupBox, 2, 0)
        layout.addWidget(self.parallel_groupBox, 2, 1)
        self.ok_button = QPushButton('Ok')
        self.cancel_button = QPushButton('Cancel')
        self.ok_button.clicked.connect(self.accept)
        self.cancel_button.clicked.connect(self.reject)
        layout.addWidget(self.ok_button, 3, 0)
        layout.addWidget(self.cancel_button, 3, 1)
        layout.setAlignment(Qt.AlignCenter)

        if install_requires:
            self.parallel_install()

        if remove_requires:
            self.parallel_remove()


# class DialogForArchiveStudentOnServer(QDialog):
#     def __init__(self):
#         super().__init__()
#         self.initUI()
#
#     def create_archive(self):
#         login = self.comboBox.currentText()
#         current_home_folder = self.users_with_home[login]
#         home_folder_path, clean_home_folder_name = current_home_folder.rsplit('/', 1)
#         run_command_by_root(f'rm -rf /home/{login}.tar.gz ; '
#                                      f'tar -C {home_folder_path} -cvf /home/{login}.tar.gz {clean_home_folder_name}')
#         result = f'{login}.tar.gz' in run_command(f'find /home/{login}.tar.gz -mmin -1')
#         dlg = QMessageBox(self)
#         dlg.setWindowTitle("Внимание")
#         dlg.setText(f"Архив /home/{login}.tar.gz создан." if result else
#                     'Введён неправильный пароль root. Архив не создан.')
#         dlg.exec()
#
#     def initUI(self):
#         self.comboBox = QComboBox(self)
#         users_with_home_command_output = run_command("getent passwd | grep '/home'").split('\n')
#         self.users_with_home = dict()
#         for line in users_with_home_command_output:
#             if ':' in line:
#                 for word in line.split(':'):
#                     if word.strip().startswith('/home'):
#                         self.users_with_home[line.split(':')[0].strip()] = word.strip()
#         self.comboBox.addItems(list(self.users_with_home.keys()))
#
#         self.layout = QVBoxLayout()
#         self.layout.addWidget(QLabel('Выберите пользователя:'))
#         self.layout.addWidget(self.comboBox)
#         ok_button = QPushButton('Ok')
#         cancel_button = QPushButton('Отмена')
#         ok_button.clicked.connect(self.create_archive)
#         cancel_button.clicked.connect(lambda: self.close())
#         self.layout.addWidget(ok_button)
#         self.layout.addWidget(cancel_button)
#         self.setLayout(self.layout)
#         self.setMinimumWidth(400)


class DialogForCopyStudentArchiveFromServer(QDialog):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.comboBox = QComboBox(self)
        self.users_with_home = run_command("getent passwd | grep '/home'").split('\n')
        while '' in self.users_with_home:
            self.users_with_home.remove('')
        for i in range(len(self.users_with_home)):
            self.users_with_home[i] = self.users_with_home[i].strip().split(':', 1)[0]
        self.comboBox.addItems(list(self.users_with_home))

        self.layout = QVBoxLayout()
        info_label = QLabel(
            'Внимание! Если вы скопируете архив ученика с сервера на хосты, это приведёт к уничтожению уже '
            'существующих там архивов в случае их наличия.\n'
            'Выберите пользователя для создания архива:'
        )
        info_label.setWordWrap(True)
        self.layout.addWidget(info_label)
        self.layout.addWidget(self.comboBox)
        ok_button = QPushButton('Ok')
        cancel_button = QPushButton('Отмена')
        ok_button.clicked.connect(lambda: self.accept())
        cancel_button.clicked.connect(lambda: self.reject())
        self.layout.addWidget(ok_button)
        self.layout.addWidget(cancel_button)
        self.setLayout(self.layout)
        self.setMinimumWidth(400)


class WindowForProgramsListToInstall(QDialog):
    def __init__(self, remove=False):
        super().__init__()
        self.remove = remove
        self.initUI()

    def popular_program_selected(self) -> None:
        """
        Меняет список программ, выбранных для установки или удаления, в текстовом поле
        """
        program_name = self.popular_programs[self.sender().text()]
        current_programs = [i for i in self.textarea.toPlainText().split('\n')]
        for i in range(len(current_programs)):
            current_programs[i] = current_programs[i].strip()
        while '' in current_programs:
            current_programs.remove('')
        if self.sender().isChecked():
            if program_name not in current_programs:
                if not current_programs:
                    self.textarea.setPlainText(program_name)
                else:
                    self.textarea.setPlainText(self.textarea.toPlainText().strip() + '\n' + program_name)
        if not self.sender().isChecked():
            if program_name in current_programs:
                current_programs.remove(program_name)
                self.textarea.setPlainText("\n".join(current_programs))

    def initUI(self):
        self.textarea = QPlainTextEdit(self)
        layout = QGridLayout()
        self.setLayout(layout)
        if not self.remove:
            layout.addWidget(QLabel('Введите программы для установки (по одной в строке):'), 0, 0)
        else:
            layout.addWidget(QLabel('Введите программы для удаления (по одной в строке):'), 0, 0)
        layout.addWidget(self.textarea, 1, 0)

        popular_programs_groupbox = QGroupBox('Популярные программы')
        popular_programs_groupbox_layout = QVBoxLayout()
        popular_programs_groupbox.setLayout(popular_programs_groupbox_layout)
        popular_programs_scrollarea = QScrollArea()
        popular_programs_widget = QWidget()
        popular_programs_widget_layout = QVBoxLayout()
        popular_programs_widget.setLayout(popular_programs_widget_layout)
        popular_programs_scrollarea.setWidget(popular_programs_widget)
        popular_programs_groupbox_layout.addWidget(popular_programs_scrollarea)
        self.popular_programs = {
            "Светофор (обновления системы)": "rosa-update-system",
            "PyCharm Community": "pycharm-community",
            "Wing 101": "wing-101",
            "Wing Personal": "wing-personal",
            "PascalABC.NET": "pascalabcnet",
            "BASIC256": "basic256",
            "Scratch Desktop": "scratch-desktop",
            "Кумир": "kumir-all",
            "Mozilla Firefox": "firefox",
            "Р7-Офис": "r7-office",
            "Менеджер архивов Engrampa": "engrampa",
            "МВКМ (мессенджер для VK)": "mos-vkm"
        }
        for program in self.popular_programs.keys():
            checkbox = QCheckBox(program)
            checkbox.stateChanged.connect(self.popular_program_selected)
            popular_programs_widget_layout.addWidget(checkbox)

        popular_programs_scrollarea.setWidgetResizable(True)
        layout.addWidget(popular_programs_groupbox, 0, 1, 2, 1)
        ok_button = QPushButton('Ok')
        cancel_button = QPushButton('Отмена')
        ok_button.clicked.connect(lambda: self.accept())
        cancel_button.clicked.connect(lambda: self.reject())
        layout.addWidget(ok_button, 2, 0)
        layout.addWidget(cancel_button, 2, 1)
        self.setWindowTitle('Введите программы')


class WindowForSetFileAssociations(QDialog):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        self.association_dictionary = {
            "PDF":
                {
                    "Okular": "okularApplication_pdf.desktop",
                    "Chromium": "chromium-browser.desktop",
                    "Firefox": "firefox.desktop"
                },
            "Web-страницы":
                {
                    "Chromium": "chromium-browser.desktop",
                    "Firefox": "firefox.desktop"
                },
            "Текстовые файлы (.txt)":
                {
                    "Kate": "kde5-org.kde.kate.desktop",
                    "KWrite": "kde5-org.kde.kwrite.desktop"
                }
        }

        self.mimetype_params = {
            "PDF": "application/pdf",
            "Web-страницы": "text/html",
            "Текстовые файлы (.txt)": "text/plain"
        }

        for key in self.association_dictionary:
            self.association_dictionary[key]['Не изменять'] = ''
        self.layout = QGridLayout()
        self.setLayout(self.layout)
        title = QLabel('Выберите ассоциации для указанных типов файлов.\n'
                       'Внимание! Убедитесь, что указанные программы установлены на выбранных хостах.')
        title.setWordWrap(True)
        self.layout.addWidget(title, 0, 0, 1, 2)

        row = 1
        for key in self.association_dictionary:
            self.layout.addWidget(QLabel(key), row, 0)
            combobox = QComboBox()
            combobox.addItems(sorted(self.association_dictionary[key].keys(), reverse=True))
            self.layout.addWidget(combobox, row, 1)
            row += 1

        ok_button = QPushButton('Ok')
        cancel_button = QPushButton('Отмена')
        ok_button.clicked.connect(lambda: self.accept())
        cancel_button.clicked.connect(lambda: self.reject())
        self.layout.addWidget(ok_button, row, 0)
        self.layout.addWidget(cancel_button, row, 1)
        self.setWindowTitle('Ассоциации файлов')
        self.setMinimumWidth(400)


def get_name_with_next_number(current_name: str) -> str:
    """
    Функция для автоинкремента имён хостов. Например, если последний в списке комп24, следующий будет комп25.
    Если числа на конце не было, будет 1.
    @param current_name: текущее имя хоста (последнее в таблице)
    @return: следующее имя хоста
    """
    cnt = ''
    right = len(current_name) - 1
    while current_name[right].isdigit():
        cnt = current_name[right] + cnt
        right -= 1
    if cnt == '':
        cnt = 1
    else:
        cnt = int(cnt) + 1
    return current_name[:right + 1] + str(cnt)


class WindowForSavingProfile(QDialog):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        layout = QGridLayout()
        self.setLayout(layout)
        layout.addWidget(QLabel('Введите или выберите из списка название профиля:'), 0, 0, 1, 2)
        self.combobox = QComboBox()
        self.combobox.setEditable(True)
        regex = QRegExp("[\w,\s-]+")
        validator = QRegExpValidator(regex)
        self.combobox.setValidator(validator)
        try:
            elements = []
            current_home_folder = run_command('xdg-user-dir').strip()
            for file in os.listdir(f'{current_home_folder}/.teacher_control/profiles'):
                if file.endswith('.json'):
                    elements.append(file[:-5])
            self.combobox.addItems(elements)
        except Exception as e:
            logging.info(f'Не удалось получить список профилей: {e}')
        self.combobox.setCurrentText('')
        layout.addWidget(self.combobox, 1, 0, 1, 2)
        ok_button = QPushButton('Ok')
        cancel_button = QPushButton('Отмена')
        ok_button.clicked.connect(lambda: self.accept())
        cancel_button.clicked.connect(lambda: self.reject())
        layout.addWidget(ok_button, 2, 0)
        layout.addWidget(cancel_button, 2, 1)
        self.setWindowTitle('Введите название')


class WindowForSelectingNewServer(QDialog):
    def __init__(self):
        super().__init__()
        self.initUI()

    def create_new_server(self):
        pass

    def initUI(self):
        layout = QGridLayout()
        self.setLayout(layout)
        info_label = QLabel('Внимание!\nДанное действие скопирует закрытый ключ veyon с данного компьютера на '
                            'другой. После этого с него можно будет управлять компьютерами в кабинете.\n'
                            'Выберите новый сервер из списка настроенных хостов:')
        info_label.setWordWrap(True)
        layout.addWidget(info_label, 0, 0, 1, 2)
        self.combobox = QComboBox()
        try:
            elements = []
            for host in self.hosts.items_to_list():
                if host.setup is True:
                    elements.append(host.hostname)
            self.combobox.addItems(elements)
        except Exception as e:
            logging.info(f'Не найдено ни одного настроенного хоста: {e}')
        layout.addWidget(self.combobox, 1, 0, 1, 2)
        new_server_button = QPushButton('Указать новый сервер')
        new_server_button.clicked.connect(self.create_new_server)
        layout.addWidget(new_server_button, 2, 0, 1, 2)
        ok_button = QPushButton('Ok')
        cancel_button = QPushButton('Отмена')
        ok_button.clicked.connect(lambda: self.accept())
        cancel_button.clicked.connect(lambda: self.reject())
        layout.addWidget(ok_button, 3, 0)
        layout.addWidget(cancel_button, 3, 1)
        self.setWindowTitle('Выберите сервер')


class WindowForCreatingNewServer(QDialog):
    def __init__(self):
        super().__init__()
        self.initUI()

    def initUI(self):
        layout = QGridLayout()
        self.setLayout(layout)
        layout.addWidget(QLabel('IP-адрес или локальное имя: '), 0, 0)
        self.address = QLineEdit()
        layout.addWidget(self.address, 0, 1)
        layout.addWidget(QLabel('Логин админа (не root): '), 1, 0)
        self.admin_login = QLineEdit()
        layout.addWidget(self.admin_login, 1, 1)
        layout.addWidget(QLabel('Пароль админа: '), 2, 0)
        self.admin_password = QLineEdit()
        layout.addWidget(self.admin_password, 2, 1)

        ok_button = QPushButton('Ok')
        cancel_button = QPushButton('Отмена')
        ok_button.clicked.connect(lambda: self.accept())
        cancel_button.clicked.connect(lambda: self.reject())
        layout.addWidget(ok_button, 3, 0)
        layout.addWidget(cancel_button, 3, 1)
        self.setWindowTitle('Выберите сервер')


class WindowForSelectPageInBrowser(QDialog):
    def __init__(self):
        super().__init__()
        self.initUI()

    def keyPressEvent(self, a0):
        """
        Обработка нажатия на Enter и Esc
        @param a0: событие клавиатуры
        """
        if a0.key() == Qt.Key_Enter or a0.key() == Qt.Key_Return:
            self.ok_clicked()
        elif a0.key() == Qt.Key_Escape:
            self.reject()

    def ok_clicked(self) -> None:
        """
        Открывает на хостах браузер с указанной страницей
        @return: None
        """
        if self.combobox.currentText().strip() == '':
            self.reject()
            dlg = QMessageBox()
            dlg.setWindowTitle("Ошибка")
            dlg.setText("Вы не указали адрес страницы для открытия")
            dlg.exec()
            return
        if self.pseudonime_checkbox.isChecked() and self.pseudonime_lineedit.text().strip() != '':
            self.history[self.pseudonime_lineedit.text().strip()] = self.combobox.currentText().strip()
        elif (self.combobox.currentText().strip() not in self.history.values() and
              self.combobox.currentText().strip() not in self.history.keys()):
            self.history[self.combobox.currentText().strip()] = self.combobox.currentText().strip()
        with open(f'{config_path}/browser_history.txt', 'w') as out:
            out.write(dumps(self.history, indent=4, ensure_ascii=False))
        if self.combobox.currentText().strip() in self.history.keys():
            self.chosen_url = self.history[self.combobox.currentText().strip()]
        else:
            self.chosen_url = self.combobox.currentText().strip()
        self.accept()

    def clean_browser_history(self) -> None:
        """
        Очистка истории страниц, которые открывались в браузере по команде
        """
        run_command(f'rm -rf {config_path}/browser_history.txt')
        self.history = dict()
        self.combobox.clear()
        logging.info('История браузера удалена.')

    def change_label_enable(self):
        """
        Изменение доступности редактирования псевдонима для страниц
        """
        if self.pseudonime_lineedit.isEnabled():
            self.pseudonime_lineedit.setDisabled(True)
        else:
            self.pseudonime_lineedit.setEnabled(True)

    def combobox_changed(self):
        """
        Преобразование псевдонима страницы (если он есть в файле с историей) в URL
        """
        if self.combobox.currentText().strip() in self.history.keys():
            self.chosen_url = self.history[self.combobox.currentText().strip()]
        else:
            self.chosen_url = self.combobox.currentText().strip()

    def initUI(self):
        self.combobox = QComboBox(self)
        self.combobox.setEditable(True)
        self.combobox.currentTextChanged.connect(self.combobox_changed)
        self.history = dict()
        try:
            with open(f'{config_path}/browser_history.txt', 'r', encoding='utf-8') as inp:
                self.history = loads(inp.read())
        except Exception as e:
            logging.info(f'История браузера не найдена. Исключение: {e}')
        self.combobox.addItems(list(reversed(self.history.keys())))
        self.combobox.setCurrentText('')
        self.chosen_url = ''
        layout = QGridLayout()
        self.setLayout(layout)
        layout.addWidget(QLabel('Введите или выберите страницу для открытия:'), 0, 0, 1, 2)
        layout.addWidget(self.combobox, 1, 0, 1, 2)
        self.pseudonime_checkbox = QCheckBox('Сохранить под псевдонимом: ')
        self.pseudonime_checkbox.setChecked(False)
        self.pseudonime_checkbox.stateChanged.connect(self.change_label_enable)
        layout.addWidget(self.pseudonime_checkbox, 2, 0)
        self.pseudonime_lineedit = QLineEdit()
        self.pseudonime_lineedit.setDisabled(True)
        layout.addWidget(self.pseudonime_lineedit, 2, 1)
        self.open_incognito_checkbox = QCheckBox('Открыть в режиме инкогнито')
        layout.addWidget(self.open_incognito_checkbox, 3, 0, 1, 2)
        self.open_fullscreen_checkbox = QCheckBox('Открыть в полноэкранном режиме')
        layout.addWidget(self.open_fullscreen_checkbox, 4, 0, 1, 2)
        clean_history_button = QPushButton('Очистить историю браузера')
        clean_history_button.clicked.connect(self.clean_browser_history)
        layout.addWidget(clean_history_button, 5, 0, 1, 2)
        ok_button = QPushButton('Ok')
        cancel_button = QPushButton('Отмена')
        ok_button.clicked.connect(self.ok_clicked)
        cancel_button.clicked.connect(lambda: self.reject())
        layout.addWidget(ok_button, 6, 0)
        layout.addWidget(cancel_button, 6, 1)
        self.setWindowTitle('Страница для открытия')


class StyledItemDelegate(QStyledItemDelegate):

    def sizeHint(self, option, index):
        parent = (super(StyledItemDelegate, self))
        s = parent.sizeHint(option, index)
        if index.parent().isValid():
            s.setHeight(20)
        else:
            s.setHeight(40)
        return s

    def paint(self, painter, option, index):
        if not index.parent().isValid():
            # Draw root item
            indent = 0
        else:
            # Calculate indentation level
            # indent = 0 * (index.internalId() + 1)
            indent = -20

        # Set item indentation
        options = QStyleOptionViewItem(option)
        options.rect.adjust(indent, 0, 0, 0)

        # Paint item
        super(StyledItemDelegate, self).paint(painter, options, index)


class users_admins_generator(QDialog):
    def __init__(self, admin=False, parent=None):
        super(users_admins_generator, self).__init__(parent)
        self.admin = admin
        self.initUI()

    def initUI(self):
        layout = QGridLayout()
        self.setLayout(layout)

        text = 'админа' if self.admin else 'ученика'
        layout.addWidget(QLabel(f'Введите универсальный логин {text}:'), 0, 0)
        self.name = QLineEdit()
        layout.addWidget(self.name, 0, 1)
        layout.addWidget(QLabel(f'Введите универсальный пароль {text}:'), 1, 0)
        self.password = QLineEdit()
        layout.addWidget(self.password, 1, 1)

        ok, cancel = QPushButton('Ok'), QPushButton('Cancel')
        ok.clicked.connect(self.get_credentials)
        cancel.clicked.connect(self.reject)
        layout.addWidget(ok, 2, 0)
        layout.addWidget(cancel, 2, 1)

    def get_credentials(self):
        self.accept()
